package com.ling.pl.core.commons.utils;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Created by bo.wang on 2016/8/14.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class DataSourceUtils {

    static Log log = LogFactory.getLog(DataSourceUtils.class);

    public static DataSource getDataSourceByConfig(String dataSourceType, String url, String driverClass, String userName, String passWord, int poolSize, String jndiName) {
        if (dataSourceType == null) {
            return getDruidDataSource(url, driverClass, userName, passWord, poolSize);
        } else if ("jndi".equals(dataSourceType)) {
            return getJndiDataSource(jndiName);
        } else {
            return getDefaultDataSource(url, driverClass, userName, passWord, poolSize);
        }
    }

    public static DataSource getDefaultDataSource(String url, String driverClass, String userName, String passWord, int poolSize) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(passWord);
        return dataSource;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public static DataSource getDruidDataSource(String url, String driverClass, String userName, String passWord, int poolSize) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(passWord);

        //建议以下值尽量一样，没必要频繁的过期空闲连接（除非比如连接池资源紧缺，可以考虑）
        dataSource.setInitialSize(poolSize);//初始化连接大小
        dataSource.setMaxActive(poolSize);//连接池最大使用连接数量
        dataSource.setMinIdle(poolSize);//连接池最小空闲

        dataSource.setMaxWait(500);//获取连接最大等待时间,这个是等待获取连接池连接时间，也不要太大，比如设置在500毫秒


        dataSource.setRemoveAbandoned(false);//打开removeAbandoned功能
        dataSource.setRemoveAbandonedTimeout(300000);// 1800秒，也就是30分钟
        dataSource.setMinEvictableIdleTimeMillis(300000);//配置一个连接在池中最小生存的时间，单位是毫秒
//        dataSource.setNumTestsPerEvictionRun(0);
        dataSource.setTimeBetweenEvictionRunsMillis(120000);//配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
        dataSource.setTestWhileIdle(false);

        dataSource.setLogAbandoned(true);//关闭abanded连接时输出错误日志
        try {
            dataSource.setFilters("stat, wall");//监控数据库
        } catch (SQLException e) {
            log.warn("druid set filters erro:" + e.getMessage());
        }
        return dataSource;
    }

    /**
     * @param jndiName java:comp/env/jdbc/MyDataSourceName
     * @return
     */
    public static DataSource getJndiDataSource(String jndiName) {
        JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiName(jndiName);
        jndiObjectFactoryBean.setResourceRef(true);
        jndiObjectFactoryBean.setProxyInterface(DataSource.class);
        return (DataSource) jndiObjectFactoryBean.getObject();
    }

    public static LocalSessionFactoryBean getLocalSessionFactoryBean(DataSource dataSource, String hibernate_dialect, String hibernate_show_sql, String hbm2ddl, String batch_size, String fetch_size, String factory_class) {

        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);

        Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.dialect", hibernate_dialect);
        hibernateProperties.setProperty("hibernate.show_sql", hibernate_show_sql);
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", hbm2ddl);
        hibernateProperties.setProperty("hibernate.jdbc.batch_size", batch_size);
        hibernateProperties.setProperty("hibernate.jdbc.fetch_size", fetch_size);
        hibernateProperties.setProperty("hibernate.query.factory_class", factory_class);

        sessionFactory.setHibernateProperties(hibernateProperties);


        String[] packagesToScan = new String[]{"com.deloitte.**.model.**"};
        sessionFactory.setPackagesToScan(packagesToScan);
        return sessionFactory;
    }

    /**
     * @param jndiName java:comp/env/jdbc/MyDataSourceName
     * @return
     */
    public DataSource getJndiLookupDataSource(String jndiName) {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(jndiName);
        return dataSource;
    }
}
